﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Text;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Windows.Forms;
using DevExpress.Web.ASPxGridView;
using DevExpress.Web.ASPxEditors;
using DevExpress.Web.Data;
using System.Collections.Generic;
using DevExpress.Web.ASPxClasses;
using DevExpress.XtraCharts.Web;
using DevExpress.XtraCharts;
using System.Collections.Specialized;

public partial class GruposIndicadores : System.Web.UI.Page
{
	#region Propiedades publicas

	public DataSet GruposDS
	{
		get
		{
			if (Session["Grupos"] == null)
			{
				GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
				DataSet grupos = gruposData.GetGrupos();
				grupos.Tables[0].PrimaryKey = new DataColumn[] { grupos.Tables[0].Columns["id"] };
				Session["Grupos"] = grupos;
			}

			return (DataSet)Session["Grupos"];
		}
	}

	public DataSet FuentesDatos
	{
		get
		{
			if (Session["FuentesDatos"] == null)
			{
                GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
                Session["FuentesDatos"] = gruposData.GetFuentesDatos();
			}
			return (DataSet) Session["FuentesDatos"];
		}
	}

	public DataSet Formatos
	{
		get
		{
			if (Session["Formatos"] == null)
			{
                GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
                Session["Formatos"] = gruposData.GetFormatos();
			}
			return (DataSet)Session["Formatos"];
		}
	}

	public DataSet MaxMin
	{
		get
		{
			if (Session["MaxMin"] == null)
			{
				DataTable dt = new DataTable();
				dt.Columns.Add("id"); dt.Columns.Add("nombre");
				DataRow dr = dt.NewRow();
				dr["id"] = "MAX"; dr["nombre"] = "Maximizar";
				dt.Rows.Add(dr);
				dr = dt.NewRow();
				dr["id"] = "MIN"; dr["nombre"] = "Minimizar";
				dt.Rows.Add(dr);
				DataSet ds = new DataSet();
				ds.Tables.Add(dt);
				Session["MaxMin"] = ds;
			}
			return (DataSet)Session["MaxMin"];
		}
	}

	public DataSet NombresUsuarios
	{
		get
		{
			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
			Session["NombresUsuarios"] = gruposData.GetNombresUsuarios();
			return (DataSet)Session["NombresUsuarios"];
		}
	}

	public DataSet CantidadSeries
	{
		get
		{
			if (Session["CantidadSeries"] == null)
			{
				GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
				Session["CantidadSeries"] = graficosData.GetCantidadSeries();
			}
			return (DataSet)Session["CantidadSeries"];
		}
	}

	public DataSet TiposGraficos
	{
		get
		{
			if (Session["TiposGraficos"] == null)
			{
				GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
				Session["TiposGraficos"] = graficosData.GetTiposGrafico();
			}
			return (DataSet)Session["TiposGraficos"];
		}
	}

	public DataSet IndicadoresAsociables
	{
		get
		{
			if(GrupoAbierto != null)
			{
				GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
				Session["IndicadoresAsociables"] = graficosData.GetIndicadoresAsociables(GrupoAbierto);
			}
			return (DataSet)Session["IndicadoresAsociables"];
		}
	}
	
	public string GrupoAbierto
	{
		get { return Session["GrupoAbierto"] != null ? Session["GrupoAbierto"].ToString() : null; }
		set { Session["GrupoAbierto"] = value; }
	}
	
	#endregion

	#region Eventos generales pagina

	protected void Page_Load(object sender, EventArgs e)
	{
		if (!IsPostBack)
			LlenarGrillaGrupos();
	}

	#endregion

	//--------------- GRUPOS ------------------//
	
	#region Grilla grupos - Eventos

	protected void ASPxGridViewGrupos_Load(object sender, EventArgs e)
	{
		//Se llena la grilla de grupos cuando cargo la pagina
		LlenarGrillaGrupos();
	}

	protected void ASPxGridViewGrupos_CustomJSProperties(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewClientJSPropertiesEventArgs e)
	{
		e.Properties["cpIsEditing"] = ASPxGridViewGrupos.IsEditing;
	}

	protected void ASPxGridViewGrupos_CellEditorInitialize(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewEditorEventArgs e)
	{
		//Fix bug cuando la grilla esta vacia
		e.Editor.ReadOnly = false;

		//Agrego el evento KeyDown a los controles de la grilla
		ASPxTextBox textBox = e.Editor as ASPxTextBox;
		if (textBox == null) return;
		textBox.ClientSideEvents.KeyDown = "editor_KeyDown";
	}

	#endregion

	#region Grilla grupos - ABM

	protected void ASPxGridViewGrupos_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
	{
		try
		{
			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
            DGrupo grupo = new DGrupo(e.NewValues["id"].ToString(), e.NewValues["id"].ToString(), e.NewValues["nombre"].ToString(), null);
			gruposData.AgregarGrupo(grupo);

			AgregarRowDataSet(grupo);

			e.Cancel = true;
			ASPxGridViewGrupos.CancelEdit();
			LlenarGrillaGrupos();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al insertar el grupo. Ver log para más información.");
		}
	}

	private void AgregarRowDataSet(DGrupo grupo)
	{
		GruposDS.AcceptChanges();
		DataRow newRow = GruposDS.Tables[0].NewRow();
		newRow["id"] = grupo.id_nuevo;
		newRow["nombre"] = grupo.nombre;
		GruposDS.Tables[0].Rows.Add(newRow);
	}

	protected void ASPxGridViewGrupos_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
	{
		try
		{
			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
            DGrupo grupo = new DGrupo(e.OldValues["id"].ToString(), e.NewValues["id"].ToString(), e.NewValues["nombre"].ToString(), null);
			gruposData.ModificarGrupo(grupo);

			ModificarGrupoDataSet(grupo);

			e.Cancel = true;
			ASPxGridViewGrupos.CancelEdit();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al actualizar el grupo. Ver log para más información.");
		}
	}

    private void ModificarGrupoDataSet(DGrupo grupo)
	{
		GruposDS.AcceptChanges();
		DataRow row = GruposDS.Tables[0].Rows.Find(grupo.id_viejo);
		row["id"] = grupo.id_nuevo;
		row["nombre"] = grupo.nombre;
	}

	protected void ASPxGridViewGrupos_RowDeleting(object sender, DevExpress.Web.Data.ASPxDataDeletingEventArgs e)
	{
		try
		{
			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
            DGrupo grupo = new DGrupo(e.Values["id"].ToString(), e.Values["id"].ToString(), string.Empty, null);
			gruposData.EliminarGrupo(grupo);

			BorrarRowDataSet(grupo);

			e.Cancel = true;
			ASPxGridViewGrupos.CancelEdit();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al eliminar el grupo. Ver log para más información.");
		}
	}

    private void BorrarRowDataSet(DGrupo grupo)
	{
		GruposDS.AcceptChanges();
		GruposDS.Tables[0].Rows.Find(grupo.id_nuevo).Delete();
	}

	private void LlenarGrillaGrupos()
	{
		try
		{
			if (Utiles.TieneDatos(GruposDS))
			{
				ASPxGridViewGrupos.DataSource = GruposDS.Tables[0];
				ASPxGridViewGrupos.DataBind();
			}
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al llenar la grilla de grupos. Ver log para más información.");
		}
	}

	#endregion

	//------------ INDICADORES ----------------//

    #region Grilla Indicadores - Eventos

	protected void ASPxGridViewIndicadores_ParseValue(object sender, DevExpress.Web.Data.ASPxParseValueEventArgs e)
	{
		try
		{
			if (e.FieldName == "intervalo_actualizacion")
				if (e.Value == null) e.Value = 0;
				else ValidarNumeroEntero(e.Value, (GridViewDataColumn)ASPxGridViewIndicadores.Columns[e.FieldName]);

			if (e.FieldName == "minimo" || e.FieldName == "maximo")
				if (e.Value == null) throw new Exception(String.Format("El campo {0} no puede estar vacio", ASPxGridViewIndicadores.Columns["minimo"].Caption));
				else ValidarNumeroDecimal(e.Value, (GridViewDataColumn)ASPxGridViewIndicadores.Columns[e.FieldName]);

			if (e.FieldName == "cant_historicos")
				if (e.Value == null) throw new Exception(String.Format("El campo {0} no puede estar vacio", ASPxGridViewIndicadores.Columns["minimo"].Caption));
				else ValidarNumeroDecimal(e.Value, (GridViewDataColumn)ASPxGridViewIndicadores.Columns[e.FieldName]);
		} catch(Exception) {}
	}
	
	protected void ASPxGridViewIndicadores_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e)
	{
		//Obtengo el id del grupo que esta expandido
		GrupoAbierto = e.Parameters;

		//Lleno la grilla de indicadores
		LlenarGrillaIndicadores();
	}
	
	private void LlenarGrillaIndicadores()
	{
		//Obtengo todos los Indicadores para el grupo desde la BD
        IndicadoresData indicadoresData = new IndicadoresData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
		DataSet datosDetalle = indicadoresData.GetIndicadoresPorGrupo(GrupoAbierto);

		//Actualizo la grilla de los Indicadores
		ASPxGridViewIndicadores.DataSource = datosDetalle.Tables[0];
		ASPxGridViewIndicadores.DataBind();
	}

	protected void ASPxGridViewIndicadores_CellEditorInitialize(object sender, ASPxGridViewEditorEventArgs e)
	{
		try
		{
			//Lleno todos los combo box de aquellas columnas que corresponda
			switch (e.Column.FieldName)
			{
				case "id_fuente_datos":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, FuentesDatos); break;
				case "id_formato_valor_actual":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, Formatos); break;
				case "id_formato_variacion":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, Formatos); break;
				case "maximiza_minimiza":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, MaxMin); break;
			}
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al inicializar la celda. Ver log para más información.");
		}
	}

	protected void ASPxGridViewIndicadores_RowValidating(object sender, ASPxDataValidationEventArgs e)
	{
		//Me fijo que esten llenos los campos que son obligatorios		
		foreach (GridViewColumn column in ASPxGridViewIndicadores.Columns)
		{
			GridViewDataColumn dataColumn = column as GridViewDataColumn;
			if (dataColumn == null) continue;
			if (Array.IndexOf(new string[] { "nombre", "descripcion", "string_conexion", "query", "query" }, dataColumn.FieldName) != -1)
				if (CampoVacio(e.NewValues[dataColumn.FieldName]))
					e.Errors[dataColumn] = String.Format("El campo \"{0}\" no puede estar vacio", dataColumn.Caption);
		}

		//Valido las longitudes de los campos
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["nombre"], 100);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["descripcion"], 200);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["string_conexion"], 200);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["nombre_responsable"], 100);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["apellido_responsable"], 100);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["email_responsable"], 150);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewIndicadores.Columns["tel_responsable"], 50);
		
		if(e.NewValues["utilizar_cache"] != null && int.Parse(e.NewValues["utilizar_cache"].ToString()) == 1)
		{
			if(int.Parse(e.NewValues["intervalo_actualizacion"].ToString()) <= 0 )
				AgregarError(e.Errors, ASPxGridViewIndicadores.Columns["intervalo_actualizacion"], String.Format("El campo {0} debe ser mayor a 0 (cero)", ASPxGridViewIndicadores.Columns["intervalo_actualizacion"].Caption));
		}

		//Muestro el mensaje de error si al menos hay un error
		if (e.Errors.Count > 0) e.RowError = "Por favor, corrija los errores";
	}

	#endregion

    #region Grilla Indicadores - ABM

    protected void ASPxGridViewIndicadores_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de detalles
			ASPxGridView gridDetalle = (sender as ASPxGridView);

			//Valido los campos antes de continuar
			gridDetalle.DoRowValidation();

            IndicadoresData indicadoresData = new IndicadoresData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a agregar el Indicador
			string id_grupo = GrupoAbierto;

			//Genero el objeto Indicador
			DIndicador indicador = CrearIndicador(e.NewValues, id_grupo, e.NewValues["nombre"].ToString());
			
			//Agrego el Indicador a la base de datos
			indicadoresData.AgregarIndicador(indicador);

			e.Cancel = true;
			gridDetalle.CancelEdit();
			
			//Refresco la informacion de la grilla de indicadores
			LlenarGrillaIndicadores();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al insertar el indicador. Ver log para más información.");
		}
	}

	protected void ASPxGridViewIndicadores_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de detalles
			ASPxGridView gridDetalle = (sender as ASPxGridView);

			//Valido los campos antes de continuar
			gridDetalle.DoRowValidation();

            IndicadoresData indicadoresData = new IndicadoresData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a modificar el Indicador
			string id_grupo = GrupoAbierto;

			//Genero el objeto Indicador
			DIndicador indicador = CrearIndicador(e.NewValues, id_grupo, e.OldValues["nombre"].ToString());

			//Modifico el Indicador en la base de datos
			indicadoresData.ModificarIndicador(indicador);

			e.Cancel = true;
			gridDetalle.CancelEdit();

			//Refresco la informacion de la grilla de indicadores
			LlenarGrillaIndicadores();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al actualizar el indicador. Ver log para más información.");
		}
	}

	protected void ASPxGridViewIndicadores_RowDeleting(object sender, DevExpress.Web.Data.ASPxDataDeletingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de detalles
			ASPxGridView gridDetalle = (sender as ASPxGridView);

            IndicadoresData indicadoresData = new IndicadoresData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a elminar el Indicador
			string id_grupo = GrupoAbierto;

			//Genero el objeto Indicador
			DIndicador indicador = CrearIndicador(e.Values, id_grupo, e.Values["nombre"].ToString());

			//Elimino el Indicador de la base de datos
			indicadoresData.EliminarIndicador(indicador);

			e.Cancel = true;
			gridDetalle.CancelEdit();

			//Refresco la informacion de la grilla de indicadores
			LlenarGrillaIndicadores();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al eliminar el indicador. Ver log para más información.");
		}
	}

	private DIndicador CrearIndicador(System.Collections.Specialized.OrderedDictionary values, string id_grupo, string nombre_viejo)
	{
 		//Genero un objeto Indicador con los datos recibidos en values
        DIndicador indicador = new DIndicador(
			id_grupo,
			values["nombre"].ToString(),
			nombre_viejo,
			values["descripcion"].ToString(),
			values["id_fuente_datos"].ToString(),
			values["string_conexion"].ToString(),
			values["query"].ToString(),
			values["id_formato_valor_actual"].ToString(),
			values["id_formato_variacion"].ToString(),
			decimal.Parse(values["minimo"].ToString()),
			decimal.Parse(values["maximo"].ToString()),
			values["maximiza_minimiza"].ToString(),
			values["utilizar_cache"] != null ? int.Parse(values["utilizar_cache"].ToString()) : 0,
			long.Parse(values["intervalo_actualizacion"].ToString()),
			int.Parse(values["cant_historicos"].ToString()),
			values["nombre_responsable"].ToString(),
			values["apellido_responsable"].ToString(),
			values["email_responsable"].ToString(),
			values["tel_responsable"].ToString()
		);

        return indicador;
	}

	#endregion

	#region Grilla Indicadores - Eventos mini resultado

	protected void CallbackPanelResultadoIndicadorOnCallback(object source, CallbackEventArgsBase e)
	{
		try
		{
			lblErrorIndicador.ClientVisible = false;
			
			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
			
			//Obtengo del parametro del callback los datos para realizar la consulta
			string[] parameter = e.Parameter.Split('|');
			string id_fuente_datos = parameter[0];
			string string_conexion = parameter[1];
			string consulta = parameter[2];
			string formato_actual = parameter[3];
			string formato_variacion = parameter[4];
			decimal minimo = decimal.Parse(parameter[5]);
			decimal maximo = decimal.Parse(parameter[6]);
			string max_min = parameter[7];
			
			//Busco el resultado de la consulta
			Manager mgr = new Manager(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
			DataSet resultado = mgr.RealizarQuery(consulta, id_fuente_datos, string_conexion);
			
			//Actualizo en el popup la informacion
			decimal valor = decimal.Parse(resultado.Tables[0].Rows[0].ItemArray[0].ToString());
			decimal valor_esperado = decimal.Parse(resultado.Tables[0].Rows[0].ItemArray[1].ToString());
			decimal variacion = mgr.GetVariacion(valor, valor_esperado, formato_variacion);
			
			int alarma = mgr.GetAlarma(valor, valor_esperado, maximo, minimo, max_min);
			
			lblValorIndicador.Text = String.Format("{0:N2}", valor);
			lblUmbralIndicador.Text = String.Format("{0:N2}", valor_esperado);
			lblVariacionIndicador.Text = String.Format("{0:N2}", variacion);			
			
			switch(alarma)
			{
				case 1: imgEstadoAlarmaIndicador.Src = "Images/bueno.png"; break;
				case 0: imgEstadoAlarmaIndicador.Src = "Images/medio.png"; break;
				case -1: imgEstadoAlarmaIndicador.Src = "Images/malo.png"; break;
			}
			imgEstadoAlarmaIndicador.Alt = alarma.ToString();
		}
		catch(Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			lblErrorIndicador.Text = "Ocurrió un error al intentar obtener los datos del indicador. Verifique la información ingresada.";
			lblErrorIndicador.ClientVisible = true;
		}
	}
	
	#endregion
	
	//------------- GRAFICOS ------------------//

	#region Grilla Graficos - Eventos

	protected void ASPxGridViewGraficos_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e)
	{
		//Obtengo el id del grupo que esta expandido
		GrupoAbierto = e.Parameters;

		//Lleno la grilla de graficos
		LlenarGrillaGraficos();
	}

	protected void ASPxGridViewGraficos_CellEditorInitialize(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewEditorEventArgs e)
	{
		try
		{			
			//Lleno todos los combo box de aquellas columnas que corresponda
			switch (e.Column.FieldName)
			{
				case "id_fuente_datos":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, FuentesDatos); break;
				case "formato_valor":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, Formatos); break;
				case "tipo_grafico":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, TiposGraficos); break;
				case "nombre_indicador_asociado":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, IndicadoresAsociables); break;
				case "cantidad_series":
					LLenarEditorComboBox((ASPxComboBox)e.Editor, CantidadSeries); break;
			}
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al inicializar la celda de edicion. Ver log para más información.");
		}
	}

	protected void ASPxGridViewGraficos_RowValidating(object sender, ASPxDataValidationEventArgs e)
	{
		//Me fijo que esten llenos los campos que son obligatorios		
		foreach (GridViewColumn column in ASPxGridViewGraficos.Columns)
		{
			GridViewDataColumn dataColumn = column as GridViewDataColumn;
			if (dataColumn == null) continue;
			if (Array.IndexOf(new string[] { "nombre", "titulo", "descripcion", "string_conexion", "query" }, dataColumn.FieldName) != -1)
				if (CampoVacio(e.NewValues[dataColumn.FieldName]))
					e.Errors[dataColumn] = String.Format("El campo \"{0}\" no puede estar vacio", dataColumn.Caption);
		}
		
		//Valido las longitudes de los campos
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["nombre"], 100);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["titulo"], 100);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["descripcion"], 200);
		ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["string_conexion"], 200);

		if (e.NewValues["tipo_grafico"] != null && e.NewValues["tipo_grafico"].ToString() != "TOR")
		{
			if (CampoVacio(e.NewValues["titulo_serie_1"]))
				AgregarError(e.Errors, ASPxGridViewGraficos.Columns["titulo_serie_1"], String.Format("El campo \"{0}\" no puede estar vacio", ASPxGridViewGraficos.Columns["titulo_serie_1"].Caption));
			if (CampoVacio(e.NewValues["titulo_eje_x"]))
				AgregarError(e.Errors, ASPxGridViewGraficos.Columns["titulo_eje_x"], String.Format("El campo \"{0}\" no puede estar vacio", ASPxGridViewGraficos.Columns["titulo_eje_x"].Caption));
			if (CampoVacio(e.NewValues["titulo_eje_y"]))
				AgregarError(e.Errors, ASPxGridViewGraficos.Columns["titulo_eje_y"], String.Format("El campo \"{0}\" no puede estar vacio", ASPxGridViewGraficos.Columns["titulo_eje_y"].Caption));

			ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["titulo_serie_1"], 100);
			ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["titulo_eje_x"], 100);
			ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["titulo_eje_y"], 100);
			
			if (int.Parse(e.NewValues["cantidad_series"].ToString()) == 2)
			{
				if (CampoVacio(e.NewValues["titulo_serie_2"]))
					AgregarError(e.Errors, ASPxGridViewGraficos.Columns["titulo_serie_2"], String.Format("El campo \"{0}\" no puede estar vacio", ASPxGridViewGraficos.Columns["titulo_serie_2"].Caption));

				ValidarLongitudCampo(e.Errors, e.NewValues, (GridViewDataColumn)ASPxGridViewGraficos.Columns["titulo_serie_2"], 100);
			}
		}

		if (e.NewValues["utilizar_cache"] != null && int.Parse(e.NewValues["utilizar_cache"].ToString()) == 1)
		{
			if (int.Parse(e.NewValues["intervalo_actualizacion"].ToString()) <= 0)
				AgregarError(e.Errors, ASPxGridViewGraficos.Columns["intervalo_actualizacion"], String.Format("El campo {0} debe ser mayor a 0 (cero)", ASPxGridViewGraficos.Columns["intervalo_actualizacion"].Caption));
		}

		//Muestro el mensaje de error si al menos hay un error
		if (e.Errors.Count > 0) e.RowError = "Por favor, corrija los errores";
	}

	protected void ASPxGridViewGraficos_ParseValue(object sender, DevExpress.Web.Data.ASPxParseValueEventArgs e)
	{
		if (e.FieldName == "intervalo_actualizacion")
			if (e.Value == null) e.Value = 0;
			else ValidarNumeroEntero(e.Value, (GridViewDataColumn)ASPxGridViewGraficos.Columns[e.FieldName]);
	}

	private void LlenarGrillaGraficos()
	{
		//Obtengo todos los Graficos para el grupo desde la BD
		GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
		DataSet datosDetalle = graficosData.GetGraficosPorGrupo(GrupoAbierto);

		//Actualizo la grilla de los Graficos
		ASPxGridViewGraficos.DataSource = datosDetalle.Tables[0];
		ASPxGridViewGraficos.DataBind();
	}

	#endregion

	#region Grilla Graficos - ABM

	protected void ASPxGridViewGraficos_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de detalles
			ASPxGridView gridDetalle = (sender as ASPxGridView);

			//Valido los campos antes de continuar
			gridDetalle.DoRowValidation();

			GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a agregar el Grafico
			string id_grupo = GrupoAbierto;
			
			//Genero el objeto Grafico
			DGrafico grafico = CrearGrafico(e.NewValues, id_grupo, e.NewValues["nombre"].ToString());

			//Agrego el Grafico a la base de datos
			graficosData.AgregarGrafico(grafico);

			e.Cancel = true;
			gridDetalle.CancelEdit();

			//Refresco la informacion de la grilla de graficos
			LlenarGrillaGraficos();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al insertar el grafico. Ver log para más información.");
		}
	}

	protected void ASPxGridViewGraficos_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de detalles
			ASPxGridView gridDetalle = (sender as ASPxGridView);

			//Valido los campos antes de continuar
			gridDetalle.DoRowValidation();

			GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a modificar el Grafico
			string id_grupo = GrupoAbierto;

			//Genero el objeto Grafico
			DGrafico grafico = CrearGrafico(e.NewValues, id_grupo, e.OldValues["nombre"].ToString());

			//Modifico el Indicador en la base de datos
			graficosData.ModificarGrafico(grafico);

			e.Cancel = true;
			gridDetalle.CancelEdit();

			//Refresco la informacion de la grilla de graficos
			LlenarGrillaGraficos();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al actualizar el grafico. Ver log para más información.");
		}
	}

	protected void ASPxGridViewGraficos_RowDeleting(object sender, DevExpress.Web.Data.ASPxDataDeletingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de detalles
			ASPxGridView gridDetalle = (sender as ASPxGridView);

			GraficosData graficosData = new GraficosData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a eliminar el Grafico
			string id_grupo = GrupoAbierto;

			//Genero el objeto Grafico
			DGrafico grafico = CrearGrafico(e.Values, id_grupo, e.Values["nombre"].ToString());

			//Elimino el Indicador de la base de datos
			graficosData.EliminarGrafico(grafico);

			e.Cancel = true;
			gridDetalle.CancelEdit();

			//Refresco la informacion de la grilla de graficos
			LlenarGrillaGraficos();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al eliminar el grafico. Ver log para más información.");
		}
	}

	private DGrafico CrearGrafico(System.Collections.Specialized.OrderedDictionary values, string id_grupo, string nombre_viejo)
	{
		//Genero un objeto Grafico con los datos recibidos en values
		DGrafico grafico = new DGrafico(
			id_grupo,
			values["nombre"].ToString(),
			nombre_viejo,
			values["titulo"].ToString(),
			values["descripcion"].ToString(),
			values["id_fuente_datos"].ToString(),
			values["string_conexion"].ToString(),
			values["query"].ToString(),
			values["tipo_grafico"].ToString(),
			values["formato_valor"].ToString(),
			values["titulo_eje_x"] != null ? values["titulo_eje_x"].ToString() : string.Empty,
			values["titulo_eje_y"] != null ? values["titulo_eje_y"].ToString() : string.Empty,
			values["titulo_serie_1"].ToString(),
			values["titulo_serie_2"] != null ? values["titulo_serie_2"].ToString() : string.Empty,
			values["nombre_indicador_asociado"].ToString(),
			values["bajo_demanda"] != null ? int.Parse(values["bajo_demanda"].ToString()) : 0,
			values["utilizar_cache"] != null ? int.Parse(values["utilizar_cache"].ToString()) : 0,
			values["intervalo_actualizacion"] != null ? long.Parse(values["intervalo_actualizacion"].ToString()) : 0,
			int.Parse(values["cantidad_series"].ToString())
		);

		return grafico;
	}

	#endregion
	
	#region Grilla Graficos - Eventos mini resultado

	protected void CallbackPanelResultadoGraficoOnCallback(object source, CallbackEventArgsBase e)
	{
		try
		{
			lblErrorGrafico.ClientVisible = false;

			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo del parametro del callback los datos para realizar la consulta
			string[] parameter = e.Parameter.Split('|');
			string id_fuente_datos = parameter[0];
			string string_conexion = parameter[1];
			string consulta = parameter[2];
			string formato_valor = parameter[3];
			string tipo_grafico = parameter[4];
			int cantidad_series = int.Parse(parameter[5]);
			string titulo = parameter[6];
			string titulo_eje_x = parameter[7];
			string titulo_eje_y = parameter[8];
			string titulo_serie_1 = parameter[9];
			string titulo_serie_2 = parameter[10];

			//Busco el resultado de la consulta
			Manager mgr = new Manager(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
			DataSet resultado = mgr.RealizarQuery(consulta, id_fuente_datos, string_conexion);

			//Actualizo el grafico en el popup
			if(Utiles.TieneDatos(resultado))
				Graficador.DibujarGrafico(chartResultadoGrafico, resultado.Tables[0], tipo_grafico, cantidad_series, formato_valor, titulo, titulo_eje_x, titulo_eje_y, titulo_serie_1, titulo_serie_2);
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			lblErrorGrafico.Text = "Ocurrió un error al generar grafico. Verifique la información ingresada.";
			lblErrorGrafico.ClientVisible = true;
		}
	}

	#endregion
	
	//-------------- USUARIOS ----------------//

	#region Grilla Usuarios - Eventos

	protected void ASPxGridViewUsuarios_CustomCallback(object sender, ASPxGridViewCustomCallbackEventArgs e)
	{
		//Obtengo el id del grupo que esta expandido
		GrupoAbierto = e.Parameters;

		//Lleno la grilla de usuarios
		LlenarGrillaUsuarios();
	}
	
	private void LlenarGrillaUsuarios()
	{
		//Obtengo todos los Usuarios vinculados a dicho grupo desde la BD
		GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);
		DataSet datosGrilla = gruposData.GetUsuariosPorGrupo(GrupoAbierto);

		//Actualizo la grilla de los Usuarios
		ASPxGridViewUsuarios.DataSource = datosGrilla.Tables[0];
		ASPxGridViewUsuarios.DataBind();
	}
	
	protected void ASPxGridViewUsuarios_CellEditorInitialize(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewEditorEventArgs e)
	{
		try
		{
			//Lleno el combo box de usuarios
			if (e.Column.FieldName == "id_usuario")
					LLenarEditorComboBox((ASPxComboBox)e.Editor, NombresUsuarios);
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al inicializar la celda de edicion. Ver log para más información.");
		}
	}

	#endregion

	#region Grilla Usuarios - ABM

	protected void ASPxGridViewUsuarios_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de usuarios
			ASPxGridView gridUsuarios = (sender as ASPxGridView);

			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a agregar el Indicador
			string id_grupo = GrupoAbierto;

			//Vinculo el usuario al grupo en la base de datos
			gruposData.VincularUsuario(e.NewValues["id_usuario"].ToString(), id_grupo);

			e.Cancel = true;
			gridUsuarios.CancelEdit();

			//Refresco la informacion de la grilla de usuarios
			LlenarGrillaUsuarios();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al vincular el usuario. Ver log para más información.");
		}
	}

	protected void ASPxGridViewUsuarios_RowDeleting(object sender, DevExpress.Web.Data.ASPxDataDeletingEventArgs e)
	{
		try
		{
			//Obtengo la grilla de usuarios
			ASPxGridView gridUsuarios = (sender as ASPxGridView);

			GruposData gruposData = new GruposData(ConfigurationManager.ConnectionStrings["StrConexionServidor"].ConnectionString);

			//Obtengo el id del grupo donde voy a agregar el Indicador
			string id_grupo = GrupoAbierto;

			//Desvinculo el usuario del grupo en la base de datos
			gruposData.DesvincularUsuario(e.Values["id_usuario"].ToString(), id_grupo);

			e.Cancel = true;
			gridUsuarios.CancelEdit();

			//Refresco la informacion de la grilla de usuarios
			LlenarGrillaUsuarios();
		}
		catch (Exception ex)
		{
            Logger.log(ConfigurationManager.AppSettings["PathToLog"], ex.Message + "\n" + ex.StackTrace);
			MessageBox.Show("Ocurrió un error al desvicular el usuario. Ver log para más información.");
		}
	}

	#endregion

	//---------------- MISC ------------------//

	#region Metodos utiles

	private void LLenarEditorComboBox(ASPxComboBox comboBox, DataSet datos)
	{
		//Carga los datos recibidos en un Dataset dentro del ComboBox
		comboBox.Items.Clear();
		comboBox.DataSource = datos;
		comboBox.DataBind();
	}

	private void ValidarNumeroDecimal(object valor, GridViewDataColumn columna)
	{
		decimal decValue;
		if (valor != null && !Decimal.TryParse(valor.ToString(), out decValue))
			throw new Exception(String.Format("El campo {0} debe ser un numero decimal", columna.Caption));
	}

	private void ValidarNumeroEntero(object valor, GridViewDataColumn columna)
	{
		int intValue;
		if (valor != null && !Int32.TryParse(valor.ToString(), out intValue))
			throw new Exception(String.Format("El campo {0} debe ser un numero entero", columna.Caption));
	}

	private void ValidarLongitudCampo(Dictionary<GridViewColumn, string> errores, OrderedDictionary valores, GridViewDataColumn columna, int longitud)
	{
		if (valores[columna.FieldName] != null && valores[columna.FieldName].ToString().Length > 100)
			AgregarError(errores, columna, String.Format("El campo {0} debe tener una longitud menor a {1} caracteres", columna.Caption, longitud.ToString()));
	}

	private void AgregarError(Dictionary<GridViewColumn, string> errores, GridViewColumn columna, string textoError)
	{
		if (errores.ContainsKey(columna)) return;
		errores[columna] = textoError;
	}

	private bool CampoVacio(object valor)
	{
		if(valor == null)
			return true;
		else
			if(valor.ToString().Trim() == string.Empty)
				return true;
		return false;
	}
	
	#endregion
}